/**
 * 
 */
package research.sbookmarking.output;

import java.util.*;
import java.util.zip.*;
import java.io.*;

import research.sbookmarking.*;

/**
 * @author <a href="mailto:aatleung@gmail.com">Albert Leung</a>
 * @version 1.0
 */
public class OutputController {

	private static OutputController anInstance = null;

	/**
	 * 
	 */
	private OutputController() {
		//do nothing
	}

	/**
	 * 
	 * @return OutputController
	 */
	public static OutputController getInstance() {
		if (anInstance==null) {
			anInstance = new OutputController();
		}
		
		return anInstance;
	}
	
	private void printDataFreq (PrintWriter writer, HashMap dataFreq) throws IOException {
		Iterator data = dataFreq.keySet().iterator();
		while (data.hasNext()){
			String key = (String)data.next();
			writer.println(key + "\t " + convert(dataFreq.get(key)));
		}
	}

	private void printTags (PrintWriter writer, HashMap data)
							throws IOException {
		
		Iterator keys = data.keySet().iterator();
		while (keys.hasNext()){
			String key = (String)keys.next();
			HashMap hashmap = (HashMap)data.get(key);

			Iterator items = hashmap.keySet().iterator();
			while (items.hasNext()){
				Object item = items.next();
				writer.println(key + "\t " + item + "\t " + 
						convert(hashmap.get(item)));
			}
		}
	}

	private boolean contains (String className, Iterator classes){
		while (classes.hasNext()) {
			if (((Class)classes.next()).getName().equals(className)) {
				return true;
			}
		}
		return false;
	}
	
	private String convert (Object obj){
		String value;
		
		List classes = Arrays.asList(obj.getClass().getInterfaces());
		if (contains("java.util.List",classes.iterator())) {
			StringBuffer temp = new StringBuffer();
			
			Iterator item = ((List)obj).iterator();
			while (item.hasNext()) {
				Object anObj = item.next();
				if (item.hasNext()) {
					temp.append(anObj + ", ");
				}
				else {
					temp.append(anObj);
				}
			}
			value = temp.toString();
		}
		else {
			value = obj.toString();
		}
			
		return value;
	}
	
	private void writeUserTags (PrintWriter writer, HashMap data) throws IOException{
		writer.println ("user\t subject\t frequency");
		printTags(writer, data);
	}
	
	private void writeBookmarkTags (PrintWriter writer, HashMap data) throws IOException{
		writer.println ("URL\t subject\t frequency");
		printTags(writer, data);
	}
	
	private void writeUsersFreq (PrintWriter writer, HashMap data) throws IOException{
		writer.println("user\t frequency");
		printDataFreq(writer,data);
	}

	private void writeTagFreq(PrintWriter writer, HashMap data) throws IOException {
		writer.println("Subject\t frequency");
		printDataFreq(writer,data);
		writer.println("NB: This data is from the post retrieved and frequency for each subject may be more.");
	}
 
	private void writeBookmarkFreq(PrintWriter writer, HashMap data) throws IOException {
		writer.println("URL\t frequency");
		printDataFreq(writer,data);
		writer.println("NB: This data is from the post retrieved and there may be more posting than shown.");
	}
 
	private void writeBookmarkUser(PrintWriter writer, HashMap data) throws IOException {
		writer.println ("URL\t user");
		printDataFreq(writer,data);
		writer.println("NB: This data is from the post retrieved and there may be more user who have bookmarked the links shown.");
	}
	
	private void writeBookmarkUserTag(PrintWriter writer, HashMap data) throws IOException {
		writer.println("URL\tuser\tsubject");
		printTags(writer,data);
		writer.println("NB: This data is from the post retrieved and there may be more user who have bookmarked the links shown.");
	}
 
	public PrintWriter getFileStream (String filename) {
		try {
		FileOutputStream fos = 
			new FileOutputStream(filename);
		GZIPOutputStream gzip = new GZIPOutputStream (fos);
		OutputStreamWriter out = new OutputStreamWriter (gzip,"UTF-8");
		PrintWriter file = new PrintWriter (out);
		
		return file;
		}
		catch (IOException e){
			throw new RuntimeException(e);
		}
	}

	public void saveRawData (String filename, List dataContainers){
		try {
			
			PrintWriter file = getFileStream(filename);
			//ObjectOutputStream file = new ObjectOutputStream (fos);
			Iterator containers = dataContainers.iterator();
			
			//file.writeObject(dataContainers);
			while (containers.hasNext()) {
				DataContainer container = (DataContainer)containers.next();
				file.println(container.getQueryName());
				
				Iterator results = container.getQueryResults().iterator();
				while (results.hasNext()) {
					file.println(results.next());
				}
			}
			file.flush();
			file.close();
		}
		catch (RuntimeException e){
			System.err.println ("Error in " + e.getClass().getName() + ": ");
			System.err.println (e.getCause());
			e.printStackTrace(System.err);
		}
	}
	
	public void saveObjectData (String filename, Object data){
		try {
			FileOutputStream fos = 
				new FileOutputStream(filename);
			GZIPOutputStream gzip = new GZIPOutputStream (fos);
			ObjectOutputStream file = new ObjectOutputStream (gzip);
			file.writeObject(data);

			file.flush();
			file.close();
		}
		catch (IOException e){
			System.err.println ("Error in " + e.getClass().getName() + ": ");
			System.err.println (e.getCause());
			e.printStackTrace(System.err);
		}
	}
	
	public void saveData (String filename, List dataContainers){
		try {
			int counter=1;
			
			Iterator containers = dataContainers.iterator();
			while (containers.hasNext()){
				DataContainer container = (DataContainer)containers.next();

				PrintWriter file = getFileStream(filename);
				
				writeUserTags (file, container.getUserTags());
				writeBookmarkTags (file,container.getUrlTags());
				writeTagFreq(file,container.getFreqTags());
				writeUsersFreq(file,container.getFreqUsers());
				writeBookmarkFreq(file,container.getFreqBookmarks());
				writeBookmarkUser(file,container.getUrlUser());
				writeBookmarkUserTag(file,container.getUrlUserTags());
				file.flush();
				file.close();
				counter++;
			}
		}
		catch (IOException e){
			System.err.println("Error occured:");
			System.err.println (e.getCause());
			e.printStackTrace(System.err);
		}
		catch (NullPointerException x){
			System.out.println ("No data was processed.");
		}
	}

	public void createXmlQuery(String filename, String queryName, String name, Iterator queryList) {
		try {
			OutputStreamWriter output = new OutputStreamWriter (new FileOutputStream(filename),"UTF-8");
			PrintWriter file = new PrintWriter (output);
			file.println ("<Setting>");
			file.println ("\t<Command classpath=\"research.sbookmarking.input.\" class=\"BookmarkCommand\">");
			file.println ("\t\t<Param name=\"container\" value=\"GeneralContainer\"/>");
			file.println ("\t\t<Param name=\"queryName\" value=\""+queryName+"\"/>");
			file.println ("\t\t<List>");

			while (queryList.hasNext()) {
				file.println ("\t\t\t<CParam name=\""+name+"\" value=\""+ queryList.next() +"\"/>");
			}

			file.println ("\t\t</List>");
			file.println ("\t</Command>");
			file.println ("</Setting>");
			file.flush();
			file.close();
		}
		catch (IOException e) {
			System.err.println ("Error occured: " + e.getCause());
			e.printStackTrace(System.err);
		}
	}
	

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
